package andrei.mower2.business;

import andrei.mower2.business.exception.PositionOutsideLawnException;
import andrei.mower2.main.i18n.MessageUtils;

public class Mower {
	
	public enum Command {
		
		D((short)90), 
		G((short)-90), 
		A((short)0);
	
		public final short rotationDegreesDeltaCW;
	
		private Command(short rotationDegreesDeltaCW) {
			this.rotationDegreesDeltaCW = rotationDegreesDeltaCW;
		}	
	}
	
	public enum Direction {
		
		N((byte)0, (byte)1, (short)0), 
		S((byte)0, (byte)-1, (short)180), 
		E((byte)1, (byte)0, (short)90), 
		W((byte)-1, (byte)0, (short)270);
		
		public byte xAdvancement, yAdvancement;
		public short degreesFromNorthCW;
	
	    private Direction(byte xAdvancement, byte yAdvancement, short degreesFromNorthCW) {
	    	this.xAdvancement = xAdvancement;
	    	this.yAdvancement = yAdvancement;
	    	this.degreesFromNorthCW = degreesFromNorthCW;
	    }
	}

	private final LawnDrivingHelper drivingHelper;
	private final MowersDrivingContext drivingContext;
	private final long mowerIndex;
	private MowerVector currentVector;
	private long commandsCount;
	
	public Mower(long mowerIndex, MowersDrivingContext drivingContext) {
		this.mowerIndex = mowerIndex;
		this.drivingHelper = LawnDrivingHelper.getInstance();
		this.drivingContext = drivingContext;
	}
	
	public void placeMower(MowerVector startVector) throws PositionOutsideLawnException {
		if(LawnDrivingHelper.getInstance().isOutsideLawn(startVector.position, drivingContext)) {
			throw new PositionOutsideLawnException(
					MessageUtils.getMessage("warn.business.mowerStartPositionOutsideLawn", 
							mowerIndex,
							startVector.position.x, 
							startVector.position.y));
		}
		currentVector = startVector;
	}
	
	public MowerVector execute(Command command) throws PositionOutsideLawnException {
		commandsCount++;
		MowerVector newMowerVector = null;
		if(Command.A.equals(command)) {
			newMowerVector = currentVector.advance();		
			if(drivingHelper.isOutsideLawn(newMowerVector.position, drivingContext)) {
				throw new PositionOutsideLawnException(
						MessageUtils.getMessage("warn.business.mowerPositionExitsLawn", 
								mowerIndex, 
								newMowerVector.position.x, 
								newMowerVector.position.y,
								commandsCount));
			}
		} else {
			newMowerVector = currentVector.rotate(command);			
		}
		currentVector = newMowerVector;		
		return currentVector;
	}

	public MowerVector getCurrentVector() {
		return currentVector;
	}

	public long getMowerIndex() {
		return mowerIndex;
	}	
}
